package org.linlinjava.litemall.brand.web;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.brand.annotation.LoginUser;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.core.util.MD5Util;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.domain.LitemallOrder;
import org.linlinjava.litemall.db.domain.LitemallOrderGoods;
import org.linlinjava.litemall.db.domain.LitemallOrderReport;
import org.linlinjava.litemall.db.service.LitemallOrderGoodsService;
import org.linlinjava.litemall.db.service.LitemallOrderReportService;
import org.linlinjava.litemall.db.service.LitemallOrderService;
import org.linlinjava.litemall.db.service.LitemallServiceService;
import org.linlinjava.litemall.db.util.OrderConstant;
import org.linlinjava.litemall.db.util.OrderGoodsConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * 商户 订单
 */
@RestController
@RequestMapping("/brand/order")
public class BrandOrderController  {
    private final Log log= LogFactory.getLog(BrandOrderController.class) ;
    @Autowired
    private LitemallOrderService orderService;
    @Autowired
    private LitemallOrderGoodsService orderGoodsService;
    @Autowired
    private LitemallOrderReportService reportService;
    @Autowired
    private LitemallServiceService serviceService;

    /**
     * 有关商户的所有订单
     * @param msg  state状态  sort(add_time,id)   condition条件    page 1  pageSize 10
     * @param userId  商户的ID
     * @return
     */
    @PostMapping("list")
    public Object list(@RequestBody String msg, @LoginUser Integer userId) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        Integer brandId = serviceService.getBelong(userId);
        Short state = JacksonUtil.parseShort(msg, "state");
        String sort = JacksonUtil.parseString(msg, "sort");
        String condition = JacksonUtil.parseString(msg, "condition");
        Integer page = JacksonUtil.parseInteger(msg, "page");
        Integer pageSize = JacksonUtil.parseInteger(msg, "pageSize");
        if (page == null || pageSize == null) {
            return ResponseUtil.badArgument();
        }
        if (page < 1 || pageSize < 1) {
            return ResponseUtil.badArgumentValue();
        }
        PageInfo<LitemallOrder> pageInfo = orderService.listBrand(brandId , state, page, pageSize, sort, condition);
        List<LitemallOrder> list = pageInfo.getList();
        for (LitemallOrder order : list) {
            Map<String, Object> map = new LinkedHashMap<>();
            List<LitemallOrderGoods> goodsList = orderGoodsService.queryByOid(order.getId());
            LocalDateTime confirmTime = order.getConfirmTime();
            LocalDateTime payCreateTime = order.getPayCreateTime();
            if (confirmTime != null) {
                order.setConfirmTime(confirmTime.plusHours(24));
            }
            if (payCreateTime != null) {
                order.setPayCreateTime(payCreateTime.plusHours(2));
            }

            map.put("commodityNum", goodsList.size());
            map.put("commodity", goodsList);
            order.setDetailInfo(map);
        }
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("totalNum", pageInfo.getTotal());
        map.put("orderList", list);
        return ResponseUtil.ok(map);
    }

    /**
     * 详情
     * @param msg   id>>brandId
     * @param userId  商户的ID
     * @return
     */
    @PostMapping("detail")
    public Object detail(@RequestBody String msg , @LoginUser Integer userId) {
        Integer id = JacksonUtil.parseInteger(msg, "id");
        if (id == null || id < 1) {
            return ResponseUtil.badArgument();
        }
        Integer brandId = serviceService.getBelong(userId);
        LitemallOrder order = orderService.detail(id);
        if (order.getBrandId().toString().equals(brandId.toString())) {
            List<LitemallOrderGoods> goodsList = orderGoodsService.queryByOid(order.getId());
            List<LitemallOrderReport> reportList = reportService.queryByOid(order.getId());
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("commodityNum", goodsList.size());
            map.put("reportNum", reportList.size());
            map.put("order", order);
            map.put("report", reportList);
            map.put("commodity", goodsList);
            return ResponseUtil.ok(map);
        } else {
            return ResponseUtil.unauthz();
        }
    }

    /**
     * 确认提交
     * @param msg  id 是订单的  price价格   freight货物   goodsList 商品列表  promiseDate承诺日期
     * @param userId
     * @return
     */
    @PostMapping("confirm")
    public Object confirm(@RequestBody String msg, @LoginUser Integer userId) {
        Integer brandId = serviceService.getBelong(userId);
        Integer orderId = JacksonUtil.parseInteger(msg, "id");
        BigDecimal goodsPrice = JacksonUtil.parseDecimal(msg, "price");
        BigDecimal freightPrice = JacksonUtil.parseDecimal(msg, "freight");
        JSONObject object = JSONObject.parseObject(msg);
        String goodsListString = object.getString("goodsList");
        List<LitemallOrderGoods> goodsList = JSONObject.parseArray(goodsListString, LitemallOrderGoods.class);
        Short promiseDate = JacksonUtil.parseShort(msg, "promiseDate");
        if (orderId == null || goodsPrice == null || promiseDate == null) {
            return ResponseUtil.badArgument();
        }
        if (goodsPrice.compareTo(new BigDecimal(0)) <= 0 || promiseDate <= 0) {
            return ResponseUtil.badArgumentValue();
        }
        LitemallOrder order = orderService.findById(orderId);
        if (goodsList != null && goodsList.size() > 1) {
            updateGoodsPrice(goodsList);
        }
        if (!order.getBrandId().equals(brandId)) {
            return ResponseUtil.unauthz();
        }
        if (!(order.getOrderStatus().equals(OrderConstant.SUBMITTED))) {
            return ResponseUtil.badArgumentValue();
        }
        order.setActualPrice(goodsPrice);
        order.setFreightPrice(freightPrice);
        order.setPromiseDate(promiseDate);
        order.setConfirmTime(LocalDateTime.now());
        order.setOrderStatus(OrderConstant.CONFIRMED);
        orderService.updateWithOptimisticLocker(order);
        return ResponseUtil.ok();
    }

    /**
     *  完成 单子  改变订单的状态  需要上传检验报告单
     * @param request
     * @param file   检验报告单
     * @param msg  id   orderId
     * @param userId   brandId
     * @return
     */
    @PostMapping("newComplete")
    @Transactional(rollbackFor = Exception.class)
    public Object newComplete(HttpServletRequest request, @RequestParam(value = "file")MultipartFile file,
                              @RequestParam String msg, @LoginUser Integer userId
    ) {
        Integer orderId = JacksonUtil.parseInteger(msg, "id");
        Integer brandId = serviceService.getBelong(userId);
        if (orderId == null || orderId < 1) {
            return ResponseUtil.badArgument();
        }
        try {
            saveFile(file, JacksonUtil.parseString(msg, "fileName"), orderId, request);
            return complete(msg, brandId);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseUtil.fail(500, e.toString());
        }
    }

    //@PostMapping("complete")
    public Object complete(@RequestBody String msg, @LoginUser Integer brandId) {
        String shipSn = JacksonUtil.parseString(msg, "shipSn");//发货编号
       // if(StringUtils.isEmpty(shipSn) || shipSn.length() < 8){throw   new RuntimeException ( "请填写最低8位的快递编号"); }
        String shipChannel = JacksonUtil.parseString(msg, "shipChannel");//发货快递公司
        Integer orderId = JacksonUtil.parseInteger(msg, "id");//订单ID
        LocalDateTime shipTime = null;
        if (orderId == null || orderId < 1) {
            return ResponseUtil.badArgument();
        }
        if (StringUtils.isAnyEmpty(shipSn, shipChannel)) {
            shipSn = null;
            shipChannel = null;
        }
        else {
            shipTime = LocalDateTime.now();
        }
        LitemallOrder order = orderService.findById(orderId);
        if (!order.getBrandId().equals(brandId)) {
            return ResponseUtil.unauthz();
        }
        if (!((order.getOrderStatus().equals(OrderConstant.PAYED)) || (order.getOrderStatus().equals(OrderConstant.ASSAYED)))) {
            return ResponseUtil.badArgumentValue();
        }
        order.setShipSn(shipSn);
        order.setShipChannel(shipChannel);
        order.setShipTime(shipTime);
        order.setOrderStatus(OrderConstant.ASSAYED);
        orderService.updateWithOptimisticLocker(order);
        return ResponseUtil.ok();
    }

    //@PostMapping("refund")
    public Object refund(@RequestBody String msg, @LoginUser Integer userId) {
        Integer brandId = serviceService.getBelong(userId);
        Integer orderId = JacksonUtil.parseInteger(msg, "id");
        if (orderId == null || orderId < 1) {
            return ResponseUtil.badArgument();
        }
        LitemallOrder order = orderService.findById(orderId);
        if (!order.getBrandId().equals(brandId)) {
            return ResponseUtil.unauthz();
        }
        if (!(order.getOrderStatus().equals(OrderConstant.PENDING))) {
            return ResponseUtil.badArgumentValue();
        }
        order.setOrderStatus(OrderConstant.REFUNDED);
        orderService.updateWithOptimisticLocker(order);
        return ResponseUtil.ok();
    }

    //@PostMapping("refundPart")
    public Object refundPart(@RequestBody String msg, @LoginUser Integer userId) {
        Integer brandId = serviceService.getBelong(userId);
        Integer orderId = JacksonUtil.parseInteger(msg, "id");
        List<Integer> goodsId = JacksonUtil.parseIntegerList(msg, "agreeList");
        if (orderId == null || orderId < 1) {
            return disputed(msg, brandId);
        }
        LitemallOrder order = orderService.findById(orderId);
        if (!order.getBrandId().equals(brandId)) {
            return ResponseUtil.unauthz();
        }
        if (!(order.getOrderStatus().equals(OrderConstant.PENDING_PART))) {
            return ResponseUtil.badArgumentValue();
        }
        if (goodsId != null && goodsId.size() > 1) {
            for (Integer i : goodsId) {
                LitemallOrderGoods temp = new LitemallOrderGoods();
                temp.setState(OrderGoodsConstant.AGREE);
                temp.setId(i);
                orderGoodsService.updateById(temp);
            }
        }

        List<LitemallOrderGoods> list = orderGoodsService.queryByStateAndOid(orderId, OrderGoodsConstant.APPLICATION);
        if (list == null || list.size() < 1) {
            order.setOrderStatus(OrderConstant.COMPLETED);
            orderService.updateWithOptimisticLocker(order);
        }
        else {
            for (LitemallOrderGoods goods : list) {
                goods.setState(OrderGoodsConstant.DISAGREE);
                orderGoodsService.updateById(goods);
            }
            order.setOrderStatus(OrderConstant.DISPUTED);
            orderService.updateWithOptimisticLocker(order);
        }
        return ResponseUtil.ok();
    }

    //@PostMapping("disputed")
    public Object disputed(@RequestBody String msg, @LoginUser Integer userId) {
        Integer brandId = serviceService.getBelong(userId);
        Integer orderId = JacksonUtil.parseInteger(msg, "id");
        if (orderId == null || orderId < 1) {
            return ResponseUtil.badArgument();
        }
        LitemallOrder order = orderService.findById(orderId);
        if (!order.getBrandId().equals(brandId)) {
            return ResponseUtil.unauthz();
        }
        if (!(order.getOrderStatus().equals(OrderConstant.PENDING) || order.getOrderStatus().equals(OrderConstant.PENDING_PART))) {
            return ResponseUtil.badArgumentValue();
        }
        order.setOrderStatus(OrderConstant.DISPUTED);
        orderService.updateWithOptimisticLocker(order);
        return ResponseUtil.ok();
    }

    private void updateGoodsPrice(List<LitemallOrderGoods> goodsList) {
        for (LitemallOrderGoods goods : goodsList) {
            LitemallOrderGoods g = new LitemallOrderGoods();
            g.setId(goods.getId());
            g.setGoodsPrice(goods.getGoodsPrice());
            orderGoodsService.updateById(g);
        }
    }

    /**
     * 不能传PNG  docx  doc     file.transferTo(new File(path));  不知道为什么不能用了..需要用底层的流方法 如下:: 而且文件创建时候也需要注意.不能用file.create
     * @param file   上传文件
     * @param fileName  文件名
     * @param orderId  订单ID
     * @param request
     * @return
     * @throws Exception
     */
 private String saveFile(MultipartFile file, String fileName, Integer orderId, HttpServletRequest request) throws Exception {
     request.setCharacterEncoding("utf-8");
     if (file != null) {
         String originalFilename = file.getOriginalFilename();
         String type = originalFilename.contains(".") ? originalFilename.substring(originalFilename.lastIndexOf(".") + 1) : null;
         if (StringUtils.isEmpty(type) || "docx".equalsIgnoreCase(type) || "doc".equalsIgnoreCase(type) || "png".equalsIgnoreCase(type)) {
             throw new Exception("文档格式不正确:禁止上传docx/doc/png");
         }
         String name = "report_" + System.currentTimeMillis() + "_" + new Random().nextInt() + "." + type;
         String realPath = System.getProperty("user.dir");
         String path = realPath + "/report/" + name;
         File dir = new File(realPath + "/report");
         if (!dir.exists()) {
             dir.mkdirs();
         }
        // file.transferTo(new File(path));

      /*   使用Servlet3.0的支持的上传文件功能时用的是StandardMultipartFile对象
          这跟创建项目时使用的spring-boot-starter-parent版本号有关,
          如果我们没有使用绝对路径的话，transferTo方法会在相对路径前添加一个location路径，即：file = new File(location, fileName);
         解决办法  1.使用绝对路径的文件    2.如下方法代替 */
         FileOutputStream os=new FileOutputStream(new File(path));
         FileCopyUtils.copy(file.getInputStream(),  os);

         if (fileName == null) {
             fileName = originalFilename;
         }
         reportService.insert(name, "order", orderId, fileName, MD5Util.getMD5(file.getInputStream()));
        return path;
     }
     return  null;
 }
}